package org.luxor.commons.zookeeper.component;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.luxor.commons.zookeeper.config.properties.ZookeeperProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Hashtable;
import java.util.List;
import java.util.Optional;

/**
 * Tree监听器，可监听指定节点下，所有子节点的增、删、改操作
 *
 * @author Mr.Yan  @date: 2020/12/23
 */
public class TreeCacheWatcher {
    private static final Logger logger = LoggerFactory.getLogger(TreeCacheWatcher.class);

    private Hashtable<String, TreeCache> treeCaches = new Hashtable<String, TreeCache>();
    private CuratorFramework curatorFramework;
    private ZookeeperProperties zookeeperProperties;

    public TreeCacheWatcher(CuratorFramework curatorFramework, ZookeeperProperties zookeeperProperties) {
        this.zookeeperProperties = zookeeperProperties;
        this.curatorFramework = curatorFramework;
    }

    /**
     * 添加
     *
     * @param treeCacheListener 监听接收器
     */
    public void addWatcher(String path, TreeCacheListener treeCacheListener) throws Exception {
        if (!StringUtils.hasText(path)) {
            return;
        }
        List<String> ignores = zookeeperProperties.getListenerIgnores();
        if (!CollectionUtils.isEmpty(ignores) && CollectionUtils.contains(ignores.iterator(), path)) {
            logger.warn("TreeWatcher监听器:[ {} ] 注册，因白名单配置原因被忽略", treeCacheListener.getClass());
            return;
        }
        if (this.treeCaches.containsKey(path)) {
            logger.warn("TreeWatcher监听器:[ {} ] 注册，因存在其它观察对象被忽略", treeCacheListener.getClass());
            return;
        }

        TreeCache treeCache = new TreeCache(curatorFramework, path);
        treeCache.getListenable().addListener(treeCacheListener);
        // 添加监听器记录
        this.treeCaches.put(path, treeCache);
        // 开启监听
        treeCache.start();
    }

    /**
     * 获取
     */
    public Optional<TreeCache> getWatcher(String path) {
        if (StringUtils.hasText(path)) {
            return Optional.ofNullable(this.treeCaches.get(path));
        }
        return Optional.empty();
    }

    public void removeWatcher(String path) {
        try {
            if (StringUtils.hasText(path)) {
                this.treeCaches.get(path).close();
            }
        } catch (Exception e) {
            // .ignore
        }
    }

}
